<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/08/15
 * Time: 20:16
 * @link http://www.lmterp.cn
 */

namespace app\common\service\purchase;

use app\common\library\Tools;
use app\common\model\FinanceCash;
use app\common\model\FinancePayment;
use app\common\model\JobFlowModule;
use app\common\model\Purchase;
use app\common\model\PurchaseException;
use app\common\model\PurchaseExchange;
use app\common\model\PurchaseInfo;
use app\common\model\PurchaseReturn;
use app\common\model\PurchaseTerpInfo;
use app\common\model\PurchaseTrack;
use app\common\service\BaseService;
use app\common\service\finance\FinanceService;
use app\common\service\product\StockService;
use app\common\status\BaseStatus;
use think\Db;
use think\exception\DbException;
use think\facade\Log;

/**
 * 退换货异常服务类
 * Class ReturnExchangeService
 * @package app\common\service\purchase
 */
class RExService extends BaseService
{
    /**
     * 添加采购后续处理商品
     * @param string[] $data 商品信息
     * @return PurchaseTerpInfo|bool
     * @date 2020/12/18
     * @author longli
     */
    public function addInfo($data = [])
    {
       $iData = PurchaseTerpInfo::getFilterField($data, '');
       if(empty($iData)) return false;
       $iData = Tools::trim($iData);
       $terpInfo = null;
       if(isset($iData['info_id'])) $terpInfo = PurchaseTerpInfo::get($iData['info_id']);
       if(empty($terpInfo) && isset($iData['id_type']) && isset($iData['ref_id']) && isset($iData['sku']))
           $terpInfo = PurchaseTerpInfo::get(['id_type' => $iData['id_type'], 'ref_id' => $iData['ref_id'], 'sku' => $iData['sku']]);
       if($pInfo = PurchaseInfo::get(['purchase_id' => $iData['purchase_id'], 'sku' => $iData['sku']]))
       {
           $iData = array_merge($iData, [
               'store_id' => $pInfo->store_id,
               'name_ch' => $pInfo->name_ch,
               'price' => $pInfo->price,
               'unit' => $pInfo->unit,
               'image_url' => $pInfo->image_url,
           ]);
       }
       if(!empty($terpInfo))
       {
           $terpInfo->save($iData);
       }
       else
       {
           $terpInfo = PurchaseTerpInfo::create($iData)->refresh();
       }
       return $terpInfo;
    }

    /**
     * 添加采购异常
     * @param string[] $data 异常信息
     * @param string[] $info 异常详情
     * @return PurchaseException|bool
     * @date 2020/12/18
     * @author longli
     */
    public function addException($data = [], array $info = [])
    {
        $eData = PurchaseException::getFilterField($data, '');
        if(empty($eData)) return false;
        $eData = Tools::trim($eData);
        $exce = null;
        if(isset($eData['eid'])) $exce = PurchaseException::get($eData['eid']);
        if(empty($exce) && isset($eData['purchase_id']) && isset($eData['sku']))
            $exce = PurchaseException::get(['purchase_id' => $eData['purchase_id'], 'sku' => $eData['sku']]);
        $purchase = Purchase::get($eData['purchase_id']);
        try
        {
            Db::startTrans();
            // 更新为异常状态
            if($purchase->getData('order_status') < Purchase::ORDER_STATUS_IN_SUCC)
            {
                $purchase->order_status = Purchase::ORDER_STATUS_EXCEPTION;
                $purchase->save();
            }
            !empty($exce)
                ? $exce->save($eData)
                : $exce = PurchaseException::create($eData)->refresh();
            if(!empty($info))
            {
                if(isset($info[0])) $info = $info[0];
                if($info['qty'] > 0)
                {
                    $info += [
                        'purchase_id' => $eData['purchase_id'],
                        'id_type' => PurchaseException::getTable(),
                        'ref_id' => $exce->eid,
                        'act_money' => '0',
                    ];
                    $this->addInfo($info);
                }
            }
            Db::commit();
        }catch (DbException $exception)
        {
            Log::info(sprintf("添加采购异常失败，单号【%s】，错误信息【%s】", Purchase::getObj($eData['purchase_id'])->purchase_sn, $exception->getMessage()));
            Db::rollback();
            return false;
        }
        return $exce;
    }

    /**
     * 添加退货单
     * @param string[] $data 退货信息
     * @param array $info 退货详情
     * @return PurchaseReturn|bool|string
     * @date 2020/12/18
     * @author longli
     */
    public function addReturn($data = [], array $info = [])
    {
        $rData = PurchaseReturn::getFilterField($data, '');
        if(empty($rData)) return false;
        $rData = Tools::trim($rData);
        $purchase = Purchase::get($rData['purchase_id']);
        if(empty($purchase)) return false;
        if(($validateMsg = $this->validateReturnExChange($purchase, $info)) !== true)
        {
            Log::info(sprintf("添加采购退货单失败，单号【%s】，错误信息【%s】", $purchase->purchase_sn, $validateMsg));
            return $validateMsg;
        }
        $logisticsPrice = isset($rData['logistics_price']) ? abs($rData['logistics_price']) : 0;
        $rData = [
            'producer_id' => $purchase->producer_id,
            'return_sn' => isset($rData['return_sn']) ? trim($rData['return_sn']) : $this->generatePr(),
            'producer_name' => $purchase->producer_name,
            'warehouse_id' => $purchase->warehouse_id,
            'check_status' => !isset($data['is_check']) || $data['is_check'] == JobFlowModule::IS_NO ? JobFlowModule::CHECK_NO_NEED : JobFlowModule::CHECK_WAIT,
            'status' => PurchaseReturn::STATUS_RETURN_NOT_OUT, // 默认为不需要发货
            'money' => $this->computeReturnPrice($purchase, $info),
        ] + $rData;
        if($data['pay_type'] == PurchaseTrack::PAY_TYPE_M && $logisticsPrice > $rData['money']) return "运费大于货值金额不能退货";
        // 如果有垫付运费
        if($data['pay_type'] == PurchaseTrack::PAY_TYPE_D) $rData['money'] += $logisticsPrice;

        $ren = null;
        if(isset($rData['ren_id'])) $ren = PurchaseReturn::get($rData['ren_id']);
        if(empty($ren)) $ren = PurchaseReturn::get(['purchase_id' => $rData['purchase_id'], 'money' => $rData['money']]);
        if(!empty($ren))
        {
            if($ren->getData('status') != PurchaseReturn::STATUS_RETURN_WAIT)
                return "退货单状态为【{$ren->status}】不能修改";
            if(in_array($ren->getData('check_status'), [JobFlowModule::CHECK_ING, JobFlowModule::CHECK_SUCC]))
                return "审批状态为【{$ren->check_status}】不修改";
        }
        try
        {
            Db::startTrans();
            // 更新为退货状态
            if($purchase->getData('order_status') < Purchase::ORDER_STATUS_RET)
            {
                $purchase->order_status = Purchase::ORDER_STATUS_RET;
                $purchase->save();
            }
            !empty($ren)
              ? $ren->save($rData)
              : $ren = PurchaseReturn::create($rData)->refresh();
            // 添加退货单
            $rType = $ren->getData('type');
            $isReturnPam = $rType == PurchaseReturn::RETURN_TYPE_PAM;
            if(!empty($info) && !isset($info[0])) $info = [$info];
            $terp = [
                'purchase_id' => $purchase->purchase_id,
                'id_type' => PurchaseReturn::getTable(),
                'ref_id' => $ren->ren_id,
            ];
            $pInfo = $purchase->info;
            foreach($info as $item)
            {
                $rQty = intval($item['qty']);
                if($rQty < 1) continue;
                // 更新采购单退货详情
                foreach($pInfo as $pf)
                {
                    if($pf->sku == $item['sku'])
                    {
                        if(in_array($rType, [PurchaseReturn::RETURN_TYPE_M, PurchaseReturn::RETURN_TYPE_NPM]))
                        {
                            $pf->exce_qty += $rQty;
                            $pf->n_store_qty = $pf->getNotStoreQty();
                            $pf->save();
                        }
                        break;
                    }
                }
                // 添加退货详情
                $terp['act_money'] = $this->computeReturnPrice($purchase, [$item]);
                if(empty($item['cost_desc'])) $item['cost_desc'] = PurchaseReturn::$RETURN_TYPE[$ren->getData('type')];
                if(!$isReturnPam) $item['qty'] = 0; // 不需要退货，重置为0
                $this->addInfo($item + $terp);
            }
            if($isReturnPam) // 退钱退货
            {
                $ren->status = PurchaseReturn::STATUS_RETURN_WAIT; // 需要发货
                // 不需要审批并且是已上架的，锁定退货库存
                if(in_array($purchase->getData('order_status'), [Purchase::ORDER_STATUS_IN_PART, Purchase::ORDER_STATUS_IN_SUCC]))
                {
                    // 占用库存成功
                    if(($lockMsg = StockService::purchaseReturnLock($ren)) === true)
                    {
                        $ren->status = PurchaseReturn::STATUS_RETURN_WAIT_OUT; // 待出库
                    }
                }
                else if(JobFlowModule::isCheckFinish($ren))
                {
                    $ren->status = PurchaseReturn::STATUS_RETURN_WAIT_OUT; // 待出库
                }
                $ren->save();
            }
            // 强制无需发货，不需要审核
            if($ren->getData('status') == PurchaseReturn::STATUS_RETURN_NOT_OUT && $ren->getData('check_status') == JobFlowModule::CHECK_WAIT)
            {
                $ren->check_status = JobFlowModule::CHECK_NO_NEED;
                $ren->save();
            }
            // 添加收款单
            if($ren->money > 0
                && in_array($purchase->getData('pay_status'), [FinancePayment::PAY_STATUS_PART, FinancePayment::PAY_STATUS_ALL])
                && !FinanceCash::hasOrderMoney($ren->return_sn, $ren->money, PurchaseReturn::getTable()))
            {
                FinanceService::getInstance()->addCash([
                    'account' => $data['account'], // 收款账号
                    'cash_type' => $data['cash_type'], // 收款方式
                    'ref_type' => BaseStatus::REF_TYPE_PURCHASE_RETURN, // 业务类型
                    'ref_id_type' => PurchaseReturn::getTable(), // 业务主表
                    'ref_sn' => $ren->return_sn, // 业务单号
                    'cash_money' => $ren->money, // 应收金额
                    'biz_date' => $data['cash_date'], // 应收款时间
                    'check_status' => !isset($data['is_check']) || $data['is_check'] == JobFlowModule::IS_NO ? JobFlowModule::CHECK_NO_NEED : JobFlowModule::CHECK_WAIT,
                    'pay_company' => $purchase->producer_name, // 付款单位
                    'cost_desc'  => '采购退货费用', // 费用说明
                ]);
            }
            // 是否有运费
            if(in_array($data['pay_type'], [PurchaseTrack::PAY_TYPE_M, PurchaseTrack::PAY_TYPE_D]) && $logisticsPrice > 0 && !FinancePayment::hasOrderSnMoney($ren->return_sn, $logisticsPrice, PurchaseReturn::getTable()))
            {
                FinanceService::getInstance()->addPayment([
                    'biz_date' => date('Y-m-d'), // 应付款日期
                    'pay_type'  => FinancePayment::PAY_TYPE_CASH, // 支付方式
                    'act_money'  => $logisticsPrice, // 应付金额
                    'ref_type'  => BaseStatus::REF_TYPE_PURCHASE_RETURN, // 业务类型
                    'ref_id_type'  => PurchaseReturn::getTable(), // 业务主表
                    'ref_sn'  => $ren->return_sn, // 业务单号
                    'cost_desc'  => '采购退货运费', // 费用说明
                ]);
            }
            Db::commit();
        }catch (DbException $exception)
        {
            Log::info(sprintf("添加采购退货单失败，单号【%s】，错误信息【%s】", $purchase->purchase_sn, $exception->getMessage()));
            Db::rollback();
            return false;
        }
        return $ren;
    }

    /**
     * 验证采购单是否可以退货
     * @param int|Purchase $purchase 采购id，或者采购单
     * @param array $info 退货信息
     * @param int $type 验证类型：1退货，2换货
     * @return bool|string
     * @date 2020/12/29
     * @author longli
     */
    public function validateReturnExChange($purchase, $info, $type = 1)
    {
        $purchase = Purchase::getObj($purchase);
        if(empty($purchase)) return "采购单不存在";
        if(empty($info)) return "退货详情为空";
        if($purchase->getData('order_status') == Purchase::ORDER_STATUS_CHE_OK)
            return "采购单已核销完成";
        $reInfo = $type == 1 ? $purchase->prenInfo : $purchase->pexchangeInfo;
        // 是否有存在退换货单
        if(!$reInfo->isEmpty())
        {
            foreach($info as & $ti)
            {
                if(empty($ti['sku'])) continue;
                foreach($reInfo as $pi)
                {
                    if($pi->sku == $ti['sku'])
                    {
                        $ti['qty'] += $pi->qty;
                        break;
                    }
                }
            }
        }
        $error = [];
        // 验证是否大于采购详情
        foreach($info as & $ti)
        {
            if(empty($ti['sku'])) continue;
            foreach($purchase->info as $pin)
            {
                if($ti['sku'] == $pin->sku)
                {
                    if($ti['qty'] > $pin->qty) $error[] = "【{$pin->sku}】大于采购数量";
                    break;
                }
            }
        }
        if(!empty($error)) return join(', ', $error);
        return true;
    }

    /**
     * 添加换货单
     * @param string[] $data 换货信息
     * @param array $info 换货明细
     * @return PurchaseExchange|bool|string
     * @date 2020/12/18
     * @author longli
     */
    public function addExchange($data = [], array $info = [])
    {
        $eData = PurchaseExchange::getFilterField($data, '');
        if(empty($info) || empty($eData)) return false;
        $eData = Tools::trim($eData);
        $purchase = Purchase::get($eData['purchase_id']);
        if(empty($purchase)) return false;
        if(($validateMsg = $this->validateReturnExChange($purchase, $info, 2)) !== true)
        {
            Log::info(sprintf("添加采购换货单失败，单号【%s】，错误信息【%s】", $purchase->purchase_sn, $validateMsg));
            return $validateMsg;
        }
        $logisticsPrice = isset($data['logistics_price']) ? abs($data['logistics_price']) : 0; // 运费
        if($data['pay_type'] == PurchaseTrack::PAY_TYPE_M && $logisticsPrice > $purchase->amo_money) return "运费大于货值金额不能换货";
        $totalMoney = $this->computeExchangePrice($purchase, $info);
        // 如果有垫付运费
        if($data['pay_type'] == PurchaseTrack::PAY_TYPE_D) $totalMoney += $logisticsPrice;
        $exchange = null;
        if(isset($eData['exchange_id'])) $exchange = PurchaseExchange::get($eData['exchange_id']);
        if(empty($exchange)) $exchange = PurchaseExchange::get(['purchase_id' => $eData['purchase_id'], 'money' => $totalMoney]);
        if(!empty($exchange))
        {
            if($exchange->getData('status') != PurchaseReturn::STATUS_RETURN_WAIT)
                return "换货单状态为【{$exchange->status}】不能修改";
            if(in_array($exchange->getData('check_status'), [JobFlowModule::CHECK_ING, JobFlowModule::CHECK_SUCC]))
                return "审批状态为【{$exchange->check_status}】不修改";
        }
        try
        {
            Db::startTrans();
            // 更新为换货状态
            if($purchase->getData('order_status') < Purchase::ORDER_STATUS_EX)
            {
                $purchase->order_status = Purchase::ORDER_STATUS_EX;
                $purchase->save();
            }
            $eData = [
                'producer_id' => $purchase->producer_id,
                'exchange_sn' => isset($eData['exchange_sn']) ? trim($eData['exchange_sn']) : $this->generatePe(),
                'check_status' => !isset($data['is_check']) || $data['is_check'] == JobFlowModule::IS_NO ? JobFlowModule::CHECK_NO_NEED : JobFlowModule::CHECK_WAIT,
                'producer_name' => $purchase->producer_name,
                'warehouse_id' => $purchase->warehouse_id,
                'money' => $totalMoney,
            ] + $eData;
            !empty($exchange)
                ? $exchange->save($eData)
                : $exchange = PurchaseExchange::create($eData)->refresh();
            // 换货明细
            $terp = [
                'purchase_id' => $purchase->purchase_id,
                'id_type' => PurchaseExchange::getTable(),
                'ref_id' => $exchange->exchange_id,
            ];
            if(!empty($info) && !isset($info[0])) $info = [$info];
            foreach($info as $item)
            {
                if($item['qty'] < 1) continue;
                $terp['act_money'] = $this->computeExchangePrice($purchase, $item);
                $this->addInfo($item + $terp);
            }
            $exchange->status = PurchaseExchange::STATUS_EXCHANGE_WAIT; // 需要发货
            // 不需要审批并且是已上架的，锁定换货库存
            if(in_array($purchase->getData('order_status'), [Purchase::ORDER_STATUS_IN_PART, Purchase::ORDER_STATUS_IN_SUCC]))
            {
                // 占用库存成功
                if(($lockMsg = StockService::purchaseExchangeLock($exchange)) === true)
                {
                    $exchange->status = PurchaseExchange::STATUS_EXCHANGE_WAIT_OUT; // 待出库
                }
            }
            else if(JobFlowModule::isCheckFinish($exchange))
            {
                $exchange->status = PurchaseExchange::STATUS_EXCHANGE_WAIT_OUT; // 待出库
            }
            $exchange->save();
            // 是否有差价
            if($totalMoney != 0)
            {
                $exchange->is_spread = PurchaseExchange::IS_YES;
                $exchange->save();
                $cashMoney = abs($totalMoney);
                // 生成收款单
                if($totalMoney > 0 && !FinanceCash::hasOrderMoney($exchange->exchange_sn, $cashMoney, PurchaseExchange::getTable()))
                {
                    FinanceService::getInstance()->addCash([
                        'account' => $data['account'], // 收款账号
                        'cash_type' => $data['cash_type'], // 收款方式
                        'ref_type' => BaseStatus::REF_TYPE_PURCHASE_EXCHANGE, // 业务类型
                        'ref_id_type' => PurchaseExchange::getTable(), // 业务主表
                        'ref_sn' => $exchange->exchange_sn, // 业务单号
                        'cash_money' => $cashMoney, // 应收金额
                        'biz_date' => $data['cash_date'], // 应收款时间
                        'check_status' => !isset($data['is_check']) || $data['is_check'] == JobFlowModule::IS_NO ? JobFlowModule::CHECK_NO_NEED : JobFlowModule::CHECK_WAIT,
                        'attach' => !empty($data['attach']) ? $data['attach'] : '', // 附件
                        'pay_company' => $purchase->producer_name, // 付款单位
                        'cost_desc'  => '采购换货费用', // 费用说明
                    ]);
                }
                // 生成付款单
                else if($totalMoney < 0 && !FinancePayment::hasOrderSnMoney($exchange->exchange_sn, $cashMoney, PurchaseExchange::getTable()))
                {
                    FinanceService::getInstance()->addPayment([
                        'biz_date' => !empty($data['cash_date']) ? $data['cash_date'] : date('Y-m-d'), // 应付款日期
                        'bank'  => $purchase->producer->bank, // 银行
                        'bank_address'  => $purchase->producer->bank_address, // 银行地址
                        'bank_user'  => $purchase->producer->bank_user, // 户名
                        'account'  => $purchase->producer->account, // 收款账号
                        'pay_type'  => $purchase->getData('pay_type'), // 支付方式
                        'act_money'  => $cashMoney, // 应付金额
                        'ref_type'  => BaseStatus::REF_TYPE_PURCHASE_EXCHANGE, // 业务类型
                        'ref_id_type'  => PurchaseExchange::getTable(), // 业务主表
                        'ref_sn'  => $exchange->exchange_sn, // 业务单号
                        'cost_desc'  => '采购换货费用', // 费用说明
                    ]);
                }
            }
            // 是否有运费
            if(in_array($data['pay_type'], [PurchaseTrack::PAY_TYPE_M, PurchaseTrack::PAY_TYPE_D]) && $logisticsPrice > 0 && !FinancePayment::hasOrderSnMoney($exchange->exchange_sn, $logisticsPrice, PurchaseExchange::getTable()))
            {
                FinanceService::getInstance()->addPayment([
                    'biz_date' => date('Y-m-d'), // 应付款日期
                    'pay_type'  => FinancePayment::PAY_TYPE_CASH, // 支付方式
                    'act_money'  => $logisticsPrice, // 应付金额
                    'ref_type'  => BaseStatus::REF_TYPE_PURCHASE_EXCHANGE, // 业务类型
                    'ref_id_type'  => PurchaseExchange::getTable(), // 业务主表
                    'ref_sn'  => $exchange->exchange_sn, // 业务单号
                    'cost_desc'  => '采购换货运费', // 费用说明
                ]);
            }
            Db::commit();
        }catch (DbException $exception)
        {
            Log::info(sprintf("添加采购换货单失败，单号【%s】，错误信息【%s】", $purchase->purchase_sn, $exception->getMessage()));
            Db::rollback();
            return false;
        }
        return $exchange;
    }

    /**
     * 计算换货单应退的商品价格
     * @param int|Purchase $purchase 采购单或采购id
     * @param array $eInfo 商品详情
     * @return float|int|string
     * @date 2020/12/30
     * @author longli
     */
    public function computeExchangePrice($purchase, $eInfo = [])
    {
        $purchase = Purchase::getObj($purchase);
        if(empty($purchase)) return "采购单不存在";
        $money = 0;
        if(!isset($eInfo[0])) $eInfo = [$eInfo];
        foreach($eInfo as $item)
        {
            if($item['qty'] < 1) continue;
            $price = isset($item['price']) ? abs($item['price']) : 0;
            // 如果大于采购单价，则直接使用采购单价
            if($price > 0 && ($piPrice = PurchaseInfo::getSkuPrice($purchase, $item['sku'])) && $price > $piPrice) $price = $piPrice;
            $money += $price * $item['qty'];
        }
        return $money;
    }

    /**
     * 计算采购退货单应退的商品价格
     * @param int|Purchase $purchase 采购单或采购id
     * @param array $rInfo 商品详情
     * @return float|string
     * @date 2020/12/29
     * @author longli
     */
    public function computeReturnPrice($purchase, $rInfo = [])
    {
        $purchase = Purchase::getObj($purchase);
        if(empty($purchase)) return "采购单不存在";
        $money = 0.0;
        if(!isset($rInfo[0])) $rInfo = [$rInfo];
        foreach($rInfo as $item)
        {
            if(empty($item['sku'])) continue;
            foreach($purchase->info as $info)
            {
                if($item['sku'] == $info->sku)
                {
                    $money += $item['qty'] * $info->price;
                    break;
                }
            }
        }
        return $money;
    }

    /**
     * 确认采购异常
     * @param int|Purchase $purchase 采购id，或者采购单
     * @param array $info 采购异常信息
     * @return Purchase|string
     * @date 2021/03/23
     * @author longli
     */
    public function abnormal($purchase, array $info = [])
    {
        $purchase = Purchase::getObj($purchase);
        if(empty($purchase)) return "采购单不存在";
        if($purchase->getData('order_status') != Purchase::ORDER_STATUS_EXCEPTION)
            return "采购单【{$purchase->purchase_sn}】状态为【{$purchase->order_status}】不能处理异常";
        if(!isset($info[0])) $info = [$info];
        foreach($purchase->info as $pf)
        {
            foreach($info as $item)
            {
                if(trim($item['sku']) == $pf->sku)
                {
                    $qty = intval($item['qty']);
                    $pf->exce_qty += $qty;
                    $pf->n_store_qty = $pf->getNotStoreQty();
                    // 如果没有待入库的数量，则把状态置为全部入库
                    if($pf->n_store_qty == 0) $pf->store_status = PurchaseInfo::STORE_SUCC;
                    $pf->save();
                    // 释放在途库存
                    $stock = \app\common\model\WarehouseStock::getWarehouseBySku($purchase->warehouse_id, $pf->sku);
                    \app\common\service\product\StockService::purchaseReleaseStock($stock, $qty);
                    break;
                }
            }
        }
        $purchase->order_status = Purchase::ORDER_STATUS_IN;
        $purchase->save();
        return $purchase;
    }

    /**
     * 退换货数量是否为未入库数量
     * @param PurchaseReturn|PurchaseExchange $re 退货货
     * @return bool
     * @date 2021/03/24
     * @author longli
     */
    public function isReNStore($re)
    {
        if(!($re instanceof PurchaseReturn || $re instanceof PurchaseExchange)) return false;
        foreach($re->purchase->info as $pf)
        {
            foreach($re->info as $rf)
            {
                if($pf->sku == $rf->sku)
                {
                    if($pf->n_store_qty != $rf->qty) return false;
                    break;
                }
            }
        }
        return true;
    }

    /**
     * 生成采购退货单号
     * @return string
     * @date 2021/01/05
     * @author longli
     */
    public function generatePr()
    {
        return self::generateSn('PR');
    }

    /**
     * 生成采购换货单号
     * @return string
     * @date 2021/01/06
     * @author longli
     */
    public function generatePe()
    {
        return self::generateSn('PE');
    }
}